package jsu.ljy.lostandfind.dao.impl;

import jsu.ljy.lostandfind.dao.BaseDao;
import jsu.ljy.lostandfind.model.Comment;
import jsu.ljy.lostandfind.util.DBUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;

import java.sql.*;
import java.util.ArrayList;
import java.util.List;

/**
 * 评论数据访问实现类
 * 
 * <p>实现了评论相关的数据库操作，包括评论的发表、修改、删除等基本操作。
 * 同时提供了按物品和用户查询评论的功能。</p>
 * 
 * @author 罗嘉毅
 * @version 1.0
 * @since 2024-03-21
 */
@Repository
public class CommentDaoImpl implements BaseDao<Comment> {
    private final UserDaoImpl userDao;
    private final ItemDaoImpl itemDao;

    /**
     * 构造函数，注入依赖的DAO组件
     * 
     * @param userDao 用户数据访问对象
     * @param itemDao 物品数据访问对象
     */
    @Autowired
    public CommentDaoImpl(UserDaoImpl userDao, ItemDaoImpl itemDao) {
        this.userDao = userDao;
        this.itemDao = itemDao;
    }

    /**
     * 保存评论信息
     * 
     * @param comment 评论信息
     * @throws RuntimeException 当数据库操作失败时抛出
     */
    @Override
    public void save(Comment comment) {
        String sql = "INSERT INTO comments (content, item_id, user_id, create_time) VALUES (?, ?, ?, ?)";
        try (Connection conn = DBUtil.getConnection();
             PreparedStatement pstmt = conn.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS)) {
            pstmt.setString(1, comment.getContent());
            pstmt.setLong(2, comment.getItemId());
            pstmt.setLong(3, comment.getUserId());
            pstmt.setTimestamp(4, new Timestamp(comment.getCreateTime().getTime()));
            pstmt.executeUpdate();
            
            // 获取生成的主键
            try (ResultSet rs = pstmt.getGeneratedKeys()) {
                if (rs.next()) {
                    comment.setId(rs.getLong(1));
                }
            }
        } catch (SQLException e) {
            throw new RuntimeException("保存评论失败", e);
        }
    }

    /**
     * 更新评论信息
     * 
     * @param comment 评论信息
     * @throws RuntimeException 当数据库操作失败时抛出
     */
    @Override
    public void update(Comment comment) {
        String sql = "UPDATE comments SET content=? WHERE id=?";
        try (Connection conn = DBUtil.getConnection();
             PreparedStatement pstmt = conn.prepareStatement(sql)) {
            pstmt.setString(1, comment.getContent());
            pstmt.setLong(2, comment.getId());
            pstmt.executeUpdate();
        } catch (SQLException e) {
            throw new RuntimeException("更新评论失败", e);
        }
    }

    /**
     * 删除评论
     * 
     * @param id 评论ID
     * @throws RuntimeException 当数据库操作失败时抛出
     */
    @Override
    public void delete(Long id) {
        String sql = "DELETE FROM comments WHERE id=?";
        try (Connection conn = DBUtil.getConnection();
             PreparedStatement pstmt = conn.prepareStatement(sql)) {
            pstmt.setLong(1, id);
            pstmt.executeUpdate();
        } catch (SQLException e) {
            throw new RuntimeException("删除评论失败", e);
        }
    }

    /**
     * 根据ID查询评论
     * 
     * @param id 评论ID
     * @return 评论信息，不存在时返回null
     * @throws RuntimeException 当数据库操作失败时抛出
     */
    @Override
    public Comment findById(Long id) {
        String sql = "SELECT * FROM comments WHERE id=?";
        try (Connection conn = DBUtil.getConnection();
             PreparedStatement pstmt = conn.prepareStatement(sql)) {
            pstmt.setLong(1, id);
            try (ResultSet rs = pstmt.executeQuery()) {
                if (rs.next()) {
                    return mapResultSetToComment(rs);
                }
            }
        } catch (SQLException e) {
            throw new RuntimeException("查询评论失败", e);
        }
        return null;
    }

    /**
     * 查询所有评论
     * 
     * @return 评论列表，按创建时间降序排序
     * @throws RuntimeException 当数据库操作失败时抛出
     */
    @Override
    public List<Comment> findAll() {
        String sql = "SELECT * FROM comments ORDER BY create_time DESC";
        List<Comment> comments = new ArrayList<>();
        try (Connection conn = DBUtil.getConnection();
             PreparedStatement pstmt = conn.prepareStatement(sql);
             ResultSet rs = pstmt.executeQuery()) {
            while (rs.next()) {
                comments.add(mapResultSetToComment(rs));
            }
        } catch (SQLException e) {
            throw new RuntimeException("查询评论列表失败", e);
        }
        return comments;
    }

    /**
     * 根据物品ID查询评论列表
     * 
     * @param itemId 物品ID
     * @return 评论列表，按创建时间降序排序
     * @throws RuntimeException 当数据库操作失败时���出
     */
    public List<Comment> findByItemId(Long itemId) {
        String sql = "SELECT * FROM comments WHERE item_id=? ORDER BY create_time DESC";
        List<Comment> comments = new ArrayList<>();
        try (Connection conn = DBUtil.getConnection();
             PreparedStatement pstmt = conn.prepareStatement(sql)) {
            pstmt.setLong(1, itemId);
            try (ResultSet rs = pstmt.executeQuery()) {
                while (rs.next()) {
                    comments.add(mapResultSetToComment(rs));
                }
            }
        } catch (SQLException e) {
            throw new RuntimeException("查询物品评论列表失败", e);
        }
        return comments;
    }

    /**
     * 根据用户ID查询评论列表
     * 
     * @param userId 用户ID
     * @return 评论列表，按创建时间降序排序
     * @throws RuntimeException 当数据库操作失败时抛出
     */
    public List<Comment> findByUserId(Long userId) {
        String sql = "SELECT * FROM comments WHERE user_id=? ORDER BY create_time DESC";
        List<Comment> comments = new ArrayList<>();
        try (Connection conn = DBUtil.getConnection();
             PreparedStatement pstmt = conn.prepareStatement(sql)) {
            pstmt.setLong(1, userId);
            try (ResultSet rs = pstmt.executeQuery()) {
                while (rs.next()) {
                    comments.add(mapResultSetToComment(rs));
                }
            }
        } catch (SQLException e) {
            throw new RuntimeException("查询用户评论列表失败", e);
        }
        return comments;
    }

    /**
     * 将ResultSet映射为Comment对象
     * 
     * @param rs 结果集
     * @return Comment对象，包含关联的用户和物品信息
     * @throws SQLException 当数据库操作失败时抛出
     */
    private Comment mapResultSetToComment(ResultSet rs) throws SQLException {
        Comment comment = new Comment();
        comment.setId(rs.getLong("id"));
        comment.setContent(rs.getString("content"));
        comment.setItemId(rs.getLong("item_id"));
        comment.setUserId(rs.getLong("user_id"));
        comment.setCreateTime(rs.getTimestamp("create_time"));

        // 加载关联的用户和物品信息
        comment.setUser(userDao.findById(comment.getUserId()));
        comment.setItem(itemDao.findById(comment.getItemId()));

        return comment;
    }
} 